﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PagedList;

namespace DLL
{
    public class ProductRepo
    {
        private string m_ConnectionString;

        public ProductRepo()
        {
            m_ConnectionString = "name=RetailManagementEntities";
        }

        public ProductRepo(string connectionString)
        {
            m_ConnectionString = connectionString;
        }

        public IList<Product> GetProducts(bool all = false)
        {
            using (RetailManagementEntities dbContext = new RetailManagementEntities(m_ConnectionString))
            {
                if (all)
                {
                    return dbContext.Product.OrderBy(x => x.Name).ToList();
                }
                else
                {
                    return dbContext.Product.Where(x => x.IsDeleted == false).OrderBy(x => x.Name).ToList();
                }
            }
        }

        public Product GetProductById(int productId)
        {
            using (RetailManagementEntities dbContext = new RetailManagementEntities(m_ConnectionString))
            {
                return dbContext.Product.Find(productId);
            }
        }

        public Product GetProductByName(string name)
        {
            using (RetailManagementEntities dbContext = new RetailManagementEntities(m_ConnectionString))
            {
                return dbContext.Product.Where(x => x.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase) && x.IsDeleted == false).FirstOrDefault();
            }
        }

        public pGetProductByBarcode_Result1 GetProductByBarcode(string barcode)
        {
            using (RetailManagementEntities dbContext = new RetailManagementEntities(m_ConnectionString))
            {
                return dbContext.pGetProductByBarcode(barcode).FirstOrDefault();
            }
        }

        public IList<Product> GetProductsByType(int productTypeId)
        {
            using (RetailManagementEntities dbContext = new RetailManagementEntities(m_ConnectionString))
            {
                return dbContext.Product.Where(x => x.IsDeleted == false &&
                    x.ProductTypeId == productTypeId).OrderBy(x => x.Name).ToList();
            }
        }

        public IList<Product> GetProductsByProducer(int producerId)
        {
            using (RetailManagementEntities dbContext = new RetailManagementEntities(m_ConnectionString))
            {
                return dbContext.Product.Where(x => x.IsDeleted == false &&
                    x.ProducerId == producerId).OrderBy(x => x.Name).ToList();
            }
        }

        public IList<Product> GetProductsByTypeAndProducer(int productTypeId, int producerId, bool all = false)
        {
            using (RetailManagementEntities dbContext = new RetailManagementEntities(m_ConnectionString))
            {
                if (all)
                {
                    return dbContext.Product.Where(x => (productTypeId == 0 || x.ProductTypeId == productTypeId) &&
                        (producerId == 0 || x.ProducerId == producerId)).OrderBy(x => x.Name).ToList();
                }
                else
                {
                    return dbContext.Product.Where(x => x.IsDeleted == false &&
                        (productTypeId == 0 || x.ProductTypeId == productTypeId) &&
                        (producerId == 0 || x.ProducerId == producerId)).OrderBy(x => x.Name).ToList();
                }
            }
        }

        public List<pSellProducts_Result> GetProductsAndSellAmount()
        {
            using (RetailManagementEntities dbContext = new RetailManagementEntities(m_ConnectionString))
            {
                return dbContext.pSellProducts().ToList();
            }
        }

        public List<pSellProductInDay_Result> GetSellProductInDay(int productId, DateTime? fromDate, DateTime? toDate)
        {
            using (RetailManagementEntities dbContext = new RetailManagementEntities(m_ConnectionString))
            {
                return dbContext.pSellProductInDay(productId, fromDate, toDate).ToList();
            }
        }

        public void AddProduct(Product product)
        {
            using (RetailManagementEntities dbContext = new RetailManagementEntities(m_ConnectionString))
            {
                dbContext.Product.Add(product);
                dbContext.SaveChanges();
            }
        }

        public void UpdateProduct(Product product)
        {
            using (RetailManagementEntities dbContext = new RetailManagementEntities(m_ConnectionString))
            {
                dbContext.pProduct_Update(product.Id, product.Name, product.SalePrice, product.ProductTypeId,
                    product.ProducerId, product.HasWarranty, product.WarrantyTime, product.WarningAmount,
                    product.Barcode, product.ListedPrice);
            }
        }

        public List<pStatisticProduct_Result> StatisticsProduct(
            out int totalInputPrice,
            string productTypeId = null, int? producerId = null, string name = null,
            bool checkWarningAmount = false, bool inputPriceChanged = false)
        {
            using (RetailManagementEntities dbContext = new RetailManagementEntities(m_ConnectionString))
            {
                var result = dbContext.pStatisticProduct(productTypeId, producerId, name, checkWarningAmount, inputPriceChanged).ToList();
                totalInputPrice = 0;
                foreach (var product in result)
                {
                    totalInputPrice += product.TotalInputPrice.Value;
                }
                return result;
            }
        }

        // TODOL should have 1 method to search product by many condition
        public List<pGetProductByCriteria_Result> GetProductByCriteria(
                int? productTypeId = null, int? producerId = null, string name = null,
                bool checkNotSalePrice = false, bool checkNotListedPrice = false, bool checkNotWarrantyTime = false,
                int? addBy = null, DateTime? fromDate = null, DateTime? toDate = null,
                bool checkInputPriceChanged = false, int? priceDiffFrom = null, int? priceDiffTo = null)
        {
            using (RetailManagementEntities dbContext = new RetailManagementEntities(m_ConnectionString))
            {
                var result = dbContext.pGetProductByCriteria(productTypeId, producerId, name,
                    checkNotSalePrice, checkNotListedPrice, checkNotWarrantyTime, addBy, fromDate, toDate,
                    checkInputPriceChanged, priceDiffFrom, priceDiffTo);
                return result.ToList();
            }
        }

        public List<pGetProductHasPriceIsNotGood_Result> GetProductHasPriceNotGood()
        {
            using (RetailManagementEntities dbContext = new RetailManagementEntities(m_ConnectionString))
            {
                var result = dbContext.pGetProductHasPriceIsNotGood();
                return result.ToList();
            }
        }

        public void DeleteProduct(int productId)
        {
            using (RetailManagementEntities dbContext = new RetailManagementEntities(m_ConnectionString))
            {
                dbContext.DeleteProduct(productId);
            }
        }

    }
}
